package encore.portal.web;

import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

import org.springframework.beans.factory.access.BeanFactoryReference;
import org.springframework.web.context.ConfigurableWebApplicationContext;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;

import encore.log.Logger;
import encore.log.LoggerFactory;
import encore.portal.PortalAppConfig;
import encore.web.ContextLoader;
/**
 * @author Plex
 * 该类实现Portlet相关信息的加载工作
 */
public class PortalStartupListener extends ContextLoader implements ServletContextListener{
    private static final Logger logger=LoggerFactory.getLogger(PortalStartupListener.class);
 
    private WebApplicationContext context;
    
	private BeanFactoryReference parentContextRef;
    /**
     * 初始化Spring的 web Context环境
     * @param servletContext
     * @return
     */
    public WebApplicationContext initWebApplicationContext(ServletContext servletContext)
    {
    	if(logger.isDebugEnabled())
    	{
    		logger.debug("开始初始化 WebApplicationContext……");
    	}
    	
    	if(servletContext.getAttribute(ContextLoader.PORTALCONTEXTID)!=null)
    	{
    	   throw new IllegalStateException("Cannot initialize context because there is already a root application context present - " +
					"check whether you have multiple ContextLoader* definitions in your web.xml!");
    	}
        
    	servletContext.log("初始化WebApplicationContext");
        try{
        
        	this.context=createWebApplicationContext(servletContext);
        	/**
        	 * 保存WebApplicationContext到Web运行环境中
        	 */
        	servletContext.setAttribute(ContextLoader.PORTALCONTEXTID, this.context);
        	currentContextPerThread.put(Thread.currentThread().getContextClassLoader(), this.context);
        	if(logger.isDebugEnabled())
        	{
        		logger.debug("Published root WebApplicationContext as ServletContext attribute with name [" +
						ContextLoader.PORTALCONTEXTID+ "]");
        	}
        	return this.context;
        }catch (RuntimeException e) {
			logger.error("初始化WebApplicationContext 失败",e);
			throw e;
		}catch (Error e) {
			logger.error("初始化WebApplicationContext 失败",e);
			throw e;
		}
        
    }
    
    
    
	private WebApplicationContext createWebApplicationContext(
			ServletContext servletContext) {
		ConfigurableWebApplicationContext wac=new AnnotationConfigWebApplicationContext();
		if (servletContext.getMajorVersion() == 2 && servletContext.getMinorVersion() < 5) {
			String servletContextName = servletContext.getServletContextName();
			if (servletContextName != null) {
				wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX + servletContextName);
			}
			else {
				wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX);
			}
		}
		else {
			wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX + servletContext.getContextPath());
		}
		
		wac.setServletContext(servletContext);
		wac.setConfigLocation(PortalAppConfig.class.toString());
		wac.refresh();
		return wac;
	}

    public void closeWebApplicationContext(ServletContext servletContext)
    {
       servletContext.log("关闭并清理 WebApplicationContext中的内容");
       try {
			if (this.context instanceof ConfigurableWebApplicationContext) {
				((ConfigurableWebApplicationContext) this.context).close();
			}
		}
		finally {
			currentContextPerThread.remove(Thread.currentThread().getContextClassLoader());
			servletContext.removeAttribute(ContextLoader.PORTALCONTEXTID);
			if (this.parentContextRef != null) {
				this.parentContextRef.release();
			}
		}
    }




	@Override
	public void contextDestroyed(ServletContextEvent event) {
	    if(logger.isDebugEnabled())
	    {
		  logger.debug("开始清理Portal服务……");
	    } 
		this.closeWebApplicationContext(event.getServletContext());
	     
	}

	@Override
	public void contextInitialized(ServletContextEvent event) {
		if(logger.isDebugEnabled())
		{
		logger.debug("开始初始化Portal 服务……");
		}
		this.initWebApplicationContext(event.getServletContext());
		
	}
	
}
